package tools

import (
	"fmt"
	"github.com/Mrs4s/MiraiGo/message"
	"math/rand"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func RollRandom(times int, max int) (result int, function string, everyFunction string) {
	var tmpFunc []string
	for i := 0; i < times; i++ {
		tmp := Random(max)
		result += tmp
		tmpFunc = append(tmpFunc, strconv.Itoa(tmp))
	}
	everyFunction = strings.Join(tmpFunc, "+")
	function = fmt.Sprintf("(%s)", everyFunction)
	return
}

func Random(height int) int {
	return rand.Intn(height) + 1
}

func AdB(function string) (times int, max int) {
	function = strings.ToLower(function)
	if strings.HasPrefix(function, "d") {
		function = "1" + function
	}

	if strings.HasSuffix(function, "d") {
		function = function + "100"
	}
	findRegex := regexp.MustCompile(`([0-9]+)d([0-9]+)`)
	params := findRegex.FindStringSubmatch(function)
	for index, param := range params {
		switch index {
		case 0:
			continue
		case 1:
			times, _ = strconv.Atoi(param)
		case 2:
			max, _ = strconv.Atoi(param)
		default:
			panic("输入格式错误")
		}
	}
	return
}

func Ri(input string, name *string) (output string, result int) {
	hasNotNum := regexp.MustCompile(`[^dD0-9+\-*\\]`)
	spaceRe, _ := regexp.Compile(`\s+`)
	input = strings.ToLower(input)
	if input == "" {
		input = "1d20"
	} else {
		ss := spaceRe.Split(input, -1)
		if len(ss) != 2 {
			output = "输入值错误，参数过多"
			result = 0
			return
		}
		for _, item := range ss {
			if hasNotNum.Match([]byte(item)) {
				*name = item
			} else {
				input = "1d20" + item
			}
		}
	}
	output = input
	findRegex := regexp.MustCompile(`([0-9]*d[0-9]*)`)
ReplaceInput:
	for {
		params := findRegex.FindStringSubmatch(input)
		if len(params) <= 1 {
			break ReplaceInput
		}
		for index, param := range params {
			if index == 0 {
				continue
			}
			_, function, _ := RollRandom(AdB(param))
			input = strings.Replace(input, param, function, index)
		}
	}
	result = MakeFunction(input)
	return
}

func Roll(input string) (output string, result int) {
	input = strings.ToLower(input)
	if input == "" {
		input = "1d100"
	}
	output = input
	findRegex := regexp.MustCompile(`([0-9]*d[0-9]*)`)
ReplaceInput:
	for {
		params := findRegex.FindStringSubmatch(input)
		if len(params) <= 1 {
			break ReplaceInput
		}
		for index, param := range params {
			if index == 0 {
				continue
			}
			_, function, _ := RollRandom(AdB(param))
			input = strings.Replace(input, param, function, index)
		}
	}
	result = MakeFunction(input)
	return
}

func RollCheck(skill int, outputMessage *message.SendingMessage) *message.SendingMessage {
	input := "1d100"
	findRegex := regexp.MustCompile(`([0-9]*d[0-9]*)`)
ReplaceInput:
	for {
		params := findRegex.FindStringSubmatch(input)
		if len(params) <= 1 {
			break ReplaceInput
		}
		for index, param := range params {
			if index == 0 {
				continue
			}
			_, function, _ := RollRandom(AdB(param))
			input = strings.Replace(input, param, function, index)
		}
	}
	result := MakeFunction(input)
	outputMessage.Append(message.NewText("掷出了:\t"))
	outputMessage.Append(message.NewText(strconv.Itoa(result)))
	outputMessage.Append(message.NewText("/"))
	outputMessage.Append(message.NewText(strconv.Itoa(skill)))
	switch {
	case result > skill && result >= 96 && skill < 50:
		outputMessage.Append(message.NewText("大失败"))
	case result == 100:
		outputMessage.Append(message.NewText("大失败"))
	case result > skill:
		outputMessage.Append(message.NewText("失败"))
	case result == 1:
		outputMessage.Append(message.NewText("大成功"))
	case result < skill/5:
		outputMessage.Append(message.NewText("极难成功"))
	case result < skill/2:
		outputMessage.Append(message.NewText("困难成功"))
	case result < skill:
		outputMessage.Append(message.NewText("成功"))
	}
	return outputMessage
}

func SanCheck(input string, outputMessage *message.SendingMessage) *message.SendingMessage {
	input = strings.ToLower(strings.TrimSpace(input))
	function1 := strings.Split(input, " ")
	sanValue, err := strconv.Atoi(function1[1])
	if err != nil {
		return nil
	}
	function2 := strings.Split(function1[0], "/")
	_, success := Roll(function2[0])
	_, failed := Roll(function2[1])
	_, random := Roll("")
	switch {
	case random > sanValue:
		outputMessage.Append(message.NewText(fmt.Sprintf("%d/%d\t失败\n损失%d点san，剩余%d", random, sanValue, failed, sanValue-failed)))
	case random <= sanValue:
		outputMessage.Append(message.NewText(fmt.Sprintf("%d/%d\t成功\n损失%d点san，剩余%d", random, sanValue, success, sanValue-success)))
	}
	return outputMessage
}
